#include <stdio.h>



#include <stdlib.h>
#include <event.h>
#include <string.h>
#include <libconfig.h>


#include "db.h"
#include "log.h"
#include "auth.h"

#include "mqtt.h"
#include "http.h"

#include "event2/http.h"

#include "event2/http_struct.h"

    struct event timer;
struct server_config_t config;
char config_filename[128];



int debug_flag = 0;
struct event_base *base = NULL;

struct event *Radauth = NULL;
struct event *Radacct = NULL;
struct event *Raddm = NULL;

static void init_config() {
    memset(&config, 0, sizeof (struct server_config_t));
    strncpy(config.radiusd_ip, "127.0.0.1", 9);
    strncpy(config.secret, "testing123", 10);
    config.mqtt_port = 8883;
    config.http_port = 8900;
    strncpy(config.db_name, "radius", 6);
    strncpy(config.db_passwd, "123456", 6);
    strncpy(config.db_server, "10.120.189.1", 32);
    config.db_port = 3306;
    //strncpy(config.db_conn, "mysql://localhost:3306/radius?user=radius&password=123456", 1024);

}

int parse_main_argv(int argc, char **argv) {
    int ret = 0;
    while ((ret = getopt(argc, argv, "hdvf:")) != -1) {
        switch (ret) {
            case 'h':
                //nac_usage();
                exit(0);
                break;

            case 'v':
                printf("1.0.0\n");
                exit(0);
                break;
            case 'f':
                strncpy(config_filename, optarg, strlen(optarg));

                break;


            case 'd':
                debug_flag = 1;
                break;
            default:
                break;
        }

    }
    return 0;
}

static int read_config(){
    config_t cfg;
    config_setting_t *setting;
    const char *str;

    config_init(&cfg);

    /* Read the file. If there is an error, report it and exit. */
    if (!config_read_file(&cfg, config_filename)) {
        printf("filename:%s\n", config_filename);
        fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
                config_error_line(&cfg), config_error_text(&cfg));
        config_destroy(&cfg);
        return (1);
    }
    if (config_lookup_string(&cfg, "dbserver", &str)) {
           memset(config.db_server,0,strlen(config.db_server));
        strncpy(config.db_server, str, strlen(str));
     
        printf("Database server: %s\n", config.db_server);
    }
    if (config_lookup_string(&cfg, "dbport", &str)) {
        config.db_port = atoi(str);
        printf("Database portal: %s\n", str);
    }
    if (config_lookup_string(&cfg, "dbname", &str)) {
        strncpy(config.db_name, str, strlen(str));
        printf("Database name: %s\n", config.db_name);
    }
    if (config_lookup_string(&cfg, "dbuser", &str)) {
        strncpy(config.db_user, str, strlen(str));
        printf("Database user: %s\n", config.db_user);
    }

    if (config_lookup_string(&cfg, "dbpasswd", &str)) {
        strncpy(config.db_passwd, str, strlen(str));
        printf("Database passwd: %s\n", config.db_passwd);
    }

    if (config_lookup_string(&cfg, "mqttserver", &str)) {
        strncpy(config.server, str, strlen(str));
        printf("MQTT Server:  %s\n", config.server);
    }
    
        if (config_lookup_string(&cfg, "mqttport", &str)) {
        config.mqtt_port = atoi(str);
        printf("MQTT Port: %d\n", config.mqtt_port);
    }
    
    if(config_lookup_string(&cfg,"secret",&str)){
        memset(config.secret,0,strlen(config.secret));
        strncpy(config.secret, str, strlen(str));
        printf("Radius shared secret:  %s\n", config.secret);
    }
    
        if (config_lookup_string(&cfg, "mqttuser", &str)) {
        strncpy(config.mqtt_username, str, strlen(str));
        printf("MQTT Username: %s\n", config.mqtt_username);
    }

    
            if (config_lookup_string(&cfg, "mqttpasswd", &str)) {
        strncpy(config.mqtt_passwd, str, strlen(str));
        printf("MQTT Password: ********\n");
    }


        if (config_lookup_string(&cfg, "httpport", &str)) {
        config.http_port = atoi(str);
        printf("HTTP Port: %d\n", config.http_port);
    }


    config_destroy(&cfg);
}
static int nacDMServerOpen(char *srvIp, char *secret, char *nasip) {
    int rc = 0;
    DEBUG("DM server ip = %s, secret = %s, nasip = %s",
            srvIp, secret, nasip);
    // 监听radius的DM下线端口
    G_auth.radDM = radclt_open_drop(srvIp, secret, nasip, 0, 1);
    if (!G_auth.radDM) {
        DEBUG("nac open DM-Handle error");
        return -1;
    }
    DEBUG("nac DM socket ID = %d", G_auth.radDM->fd);
    // 注册回调函数： 接收DM下线报文
    Raddm = event_new(base, G_auth.radDM->fd, EV_READ | EV_PERSIST, RadDMServerCallBack, (void*) base);
    event_add(Raddm, NULL);
    return rc;
}

static void del_timer_cb(const int fd, const short event, void *arg){
   int r= delete_finished_session();
   DEBUG("+++++i=%d",r);
     struct timeval tv;
                tv.tv_sec = 5;
                tv.tv_usec = 0;
   event_add(&timer, &tv);
}




int main(int argc, char** argv) {

    init_config();
    parse_main_argv(argc, argv);
    read_config();
    if (0 == debug_flag) {
   
        daemon(1, 1);

    } 
    


    if(open_db(config.db_server, config.db_port, config.db_user, config.db_passwd, config.db_name)<0){
        printf("Connect database failed!\n");
        exit(1);
    }
    DEBUG("Connecting database ...\tOK");
        if ((base = event_base_new()) == NULL) {
        DEBUG("nac libevent initialized failed.");
        return -1;
    }
httpServerInit(base, "0.0.0.0", config.http_port);
        pthread_t threadId = 0;
        int ret = pthread_create(&threadId, 0, coa_msg, NULL);
        if(ret < 0 ){
            return -1;
        }
    nacDMServerOpen("0.0.0.0", config.secret, config.radiusd_ip);

    
    

     struct timeval tv;
                tv.tv_sec = 5;
                tv.tv_usec = 0;
                
 
                evtimer_set(&timer, del_timer_cb, NULL);
                event_base_set(base, &timer);
    event_add(&timer, &tv);


   event_base_dispatch(base);
    return (0);
#if 0  
    exit(0);
    open_db("10.0.0.92", 3306, "radius", "d43huFjhR643LT", "radius");
    if ((base = event_base_new()) == NULL) {
        DEBUG("nac libevent initialized failed.");
        return -1;
    }
    char nasip[32] = {'\0'};

    /*
        if(find_session("aaa","7C5A9E4C-5951-406A-826A-F0EDF11631F8", nasip)<0){
            //DEBUG("Not found user %s",aaa);
            return -1;
        }
     */
    /*
        pthread_t threadId = 0;
        int ret = pthread_create(&threadId, 0, sub_coa_msg, NULL);
        if(ret < 0 ){
            return -1;
        }
     */
    httpServerInit(base, "0.0.0.0", 8888);

    printf("nasip=%s\n", nasip);
    nacDMServerOpen("0.0.0.0", config.secret, config.radiusd_ip);

    event_base_dispatch(base);
    return (0);
#endif
}

